package com.library.common.base

import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.*
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModelProvider
import com.library.common.R
import com.library.common.widget.VersionDialog
import com.library.common.dialog.DownAppDialog
import com.library.common.dto.MessageEvent
import com.library.common.dto.SyetemDto
import com.library.common.ext.*
import com.library.common.toast.XToast
import com.library.common.util.AppManager
import com.library.common.util.SdCardUtil
import com.library.common.util.StatusBarUtil
import com.library.common.util.StatusBarUtils
import com.library.common.widget.BGButton
import com.yanzhenjie.permission.AndPermission
import com.yanzhenjie.permission.runtime.Permission
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.io.File
import java.lang.reflect.ParameterizedType
import kotlin.math.ceil

/**
 * 作者：SimGa
 * 日期：2019-11-26
 * 时间：16:48
 */
abstract class BaseActivity<VM : BaseViewModel, DB : ViewDataBinding> : AppCompatActivity(){
    lateinit var viewModel: VM
    lateinit var mContext: BaseActivity<*, *>
    lateinit var mBinding: DB
    lateinit var mRlTitleBar: LinearLayout
    lateinit var mIvBack: ImageView
    lateinit var mIvRight: ImageView
    lateinit var mTvTitle: TextView
    lateinit var mTvRight: BGButton
    private var bodyView: ViewGroup? = null
    private val stateBar: Int
        get() {
            try {
                val c = Class.forName("com.android.internal.R\$dimen")
                val obj = c.newInstance()
                val field = c.getField("status_bar_height")
                val x = Integer.parseInt(field.get(obj).toString())
                return resources.getDimensionPixelSize(x) + ceil((50 * resources.displayMetrics.density).toDouble()).toInt()
            } catch (e: Exception) {
                e.printStackTrace()
            }

            return ceil((76 * this.resources.displayMetrics.density).toDouble()).toInt()
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        (javaClass.simpleName).logE("当前打开的页面")
        mContext = this
        initViewDataBinding(layoutId)
        viewModel = createViewModel()
        if (intent != null && intent.extras != null) {
            onGetBundle(intent.extras)
        }
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }
        initView(savedInstanceState)
        initLoadingUiChange()
        observeData()
        eventHandling()
        AppManager.get().addActivity(mContext)
    }

    protected abstract val isUseBaseTitleBar: Boolean
    protected abstract val layoutId: Int
    protected abstract fun initView(savedInstanceState: Bundle?)
    open fun onGetBundle(bundle: Bundle?) {}
    open fun eventHandling() {}
    open fun observeData() {}
    open fun handleEvent(msg: MessageModel) {}

    @Subscribe(threadMode = ThreadMode.MAIN)
    open fun onEvent(event: MessageEvent) {
    }

    /**
     * 是否设置状态栏字体图标为深色模式
     *
     * @return
     */
    protected open fun isSetStatusBarDarkMode(): Boolean {
        return true
    }


    private fun initViewDataBinding(layoutResID: Int) {
        val cls =
            (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class<*>
        val window = window
//        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
//        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
//        StatusBarUtils.darkStyle(this,Color.parseColor("#ffffff"))
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.decorView.systemUiVisibility =
            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.statusBarColor = Color.TRANSPARENT
        }
        if (isSetStatusBarDarkMode()) {//设置字体为深色
            StatusBarUtil.statusBarDarkMode(mContext)
        }
        if (isUseBaseTitleBar) {//需要公用的标题栏
            bodyView = findViewById(Window.ID_ANDROID_CONTENT)
            val contentView = LayoutInflater.from(mContext).inflate(layoutResID, null)
            val titleBarView = LayoutInflater.from(mContext).inflate(R.layout.widget_title, null)
            val fl = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT
            )
            fl.topMargin = stateBar
            bodyView?.addView(contentView, fl)
            val titleBar =
                LinearLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, stateBar)
            bodyView?.addView(titleBarView, titleBar)
            if (ViewDataBinding::class.java != cls &&
                ViewDataBinding::class.java.isAssignableFrom(cls)
            ) {
                mBinding = DataBindingUtil.bind(contentView)!!
            } else super.setContentView(layoutResID)
            mIvBack = findViewById(R.id.iv_back)
            mRlTitleBar = findViewById(R.id.rl_title)
            mTvTitle = findViewById(R.id.tv_title)
            mTvRight = findViewById(R.id.tv_right)
            mIvRight = findViewById(R.id.iv_right)
            setBackClick()
        } else {
            if (layoutResID != 0) {
                if (ViewDataBinding::class.java != cls &&
                    ViewDataBinding::class.java.isAssignableFrom(cls)
                ) {
                    mBinding = DataBindingUtil.setContentView(this, layoutResID)
                } else super.setContentView(layoutResID)
            }
        }
        mBinding.lifecycleOwner = this
    }

    private fun setBackClick() {
        if (mIvBack != null) {
            mIvBack.setOnClickListener { finish() }
        }
    }

    // 设置标题
    fun setTitle(title: String) {
        runOnUiThread {
            if (mTvTitle != null) {
                mTvTitle.text = title
            }
        }
    }

    override fun onDestroy() {
        (javaClass.simpleName).logE("当前关闭的页面 : ")
        //通知系统进行一次回收
        System.gc()
        EventBus.getDefault().unregister(this)
        super.onDestroy()
    }

    /**
     * 注册 UI 事件
     */
    private fun initLoadingUiChange() {
        viewModel.defUI.run {
            loading.observeInActivity(this@BaseActivity) {
                if (it.isShow) {
                    showLoadingExt(it.loadingMessage)
                } else {
                    dismissLoadingExt()
                }
            }
            msgEvent.observeInActivity(this@BaseActivity) {
                handleEvent(it)
            }
        }
    }

    /**
     * 覆写finish方法，覆盖默认方法，加入切换动画
     */
    override fun finish() {
        super.finish()
        AppManager.get().removeActivity(this)
        overridePendingTransition(R.anim.slide_right_in, R.anim.slide_right_out)
    }

    fun finishResult(intent: Intent?) {
        if (intent == null) {
            setResult(RESULT_OK)
        } else {
            setResult(RESULT_OK, intent)
        }
        this.finish()
    }

    protected fun onClick(onClick: (view: View) -> Unit, vararg views: View) {
        views.forEach {
            it.clickNoRepeat(500) { view ->
                onClick.invoke(view)
            }
        }
    }

    /**
     * 覆写startactivity方法，加入切换动画
     */
    fun startActivity(bundle: Bundle?, target: Class<*>) {
        val intent = Intent(this, target)
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        startActivity(intent)
        // 动画切换
        overridePendingTransition(R.anim.slide_left_in, R.anim.slide_left_out)
    }

    /**
     * 带回调的跳转
     *
     * @param bundle
     * @param requestCode
     * @param target
     */
    fun startForResult(bundle: Bundle?, requestCode: Int, target: Class<*>) {
        val intent = Intent(this, target)
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        startActivityForResult(intent, requestCode)
        overridePendingTransition(R.anim.slide_left_in, R.anim.slide_left_out)
    }

    /**
     * 创建 ViewModel
     */
    private fun createViewModel(): VM {
        return ViewModelProvider(this).get(getVmClazz(this))
    }

    protected fun pressiom(phone: String?) {
        AndPermission.with(this)
            .runtime()
            .permission(
                Permission.READ_PHONE_STATE,
                Permission.CALL_PHONE
            )
            .onDenied {
                if (AndPermission.hasAlwaysDeniedPermission(this, it)) {
                    // 这些权限被用户总是拒绝。
                    XToast.normal("需要必要权限以正常使用功能")
                }
            }
            .onGranted {
                callPhone(phone)
            }.start()
    }

    /**
     * 拨打电话（跳转到拨号界面，用户手动点击拨打）
     *
     * @param phoneNum 电话号码
     */
    private fun callPhone(phoneNum: String?) {
        val intent = Intent(Intent.ACTION_DIAL)
        val data = Uri.parse("tel:$phoneNum")
        intent.data = data
        startActivity(intent)
    }

    //是否有打开允许安装APP
    protected fun checkInstallAllowed(): Boolean {
        return if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {// Android8.0以上需要判断
            val installAllowed = packageManager.canRequestPackageInstalls()//是否允许安装包
            installAllowed
        } else {//否则直接安装
            true
        }
    }

    protected fun gotoSetting() {
        //跳转到设置页面，设置成允许安装
        val intent = Intent(
            android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
            Uri.parse("package:$packageName")
        )
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        startActivity(intent)
    }

    /**
     * 安装APP
     */
    protected fun installApk(context: Context?, fileName: String) {
        //安装应用
        val apkFile = File(SdCardUtil.get(context).DEFAULT_DOWNLOAD_PATH, fileName)
        val intent = Intent(Intent.ACTION_VIEW)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        if (apkFile == null) {
            throw NullPointerException()
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            val contentUri = FileProvider.getUriForFile(
                applicationContext,
                "${"com.zhongzhou.mobile.oil"}.fileProvider", apkFile
            )
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive")
        } else {
            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive")
        }
        startActivity(intent)
    }

    protected fun getVersionName(context: Context): String? {
        var pi: PackageInfo? = null
        try {
            val pm = context.packageManager
            pi = pm.getPackageInfo(
                context.packageName,
                PackageManager.GET_CONFIGURATIONS
            )
            return pi.versionName
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return ""
    }

    private var dialog: VersionDialog? = null
    private var downAppDialog: DownAppDialog? = null
    fun showCheckVerson(version: SyetemDto) {
        val versionCode = getVersionName(applicationContext)!!.replace(".", "").toInt()
        when (version.version.replace(".", "").toInt() > versionCode) {//判断当前版本是不是最新版
            true -> {//是
                if (dialog == null) {
                    dialog = VersionDialog(
                        this,
                        version.versionDesc,
                        version.version,
                        version.isForce,
                        version.url
                    )
                }
            }
            else -> {
                when (javaClass.simpleName) {
                    "SettingActivity" -> XToast.normal("当前已经是最新版本")
                }
            }
        }
        if (dialog != null) {
            dialog!!.setListenter { _, url ->
                AndPermission.with(this)
                    .runtime()
                    .permission(Permission.Group.STORAGE)
                    .onDenied {
                        if (AndPermission.hasAlwaysDeniedPermission(this, it)) {
                            // 这些权限被用户总是拒绝。
                            XToast.normal("无权限，请到权限中心打开相关权限")
                        } else {
                            XToast.normal("无法获取权限，应用无法更新")
                        }
                    }
                    .onGranted {
                        SdCardUtil.get(appContext).initFileDir()
                        val fileName = "Malaysia_" + version.version + ".apk";
                        val apkFile = File(
                            SdCardUtil.get(appContext).DEFAULT_DOWNLOAD_PATH,
                            fileName
                        )
                        if (apkFile.exists()) {//如果文件存在，就直接安装
                            if (!checkInstallAllowed()) {
                                gotoSetting()
                            } else {
                                installApk(appContext, fileName)
                            }
                        } else {//不存在，打开下载页面
                            if (downAppDialog == null) {
                                downAppDialog =
                                    DownAppDialog(
                                        mContext,
                                        url,
                                        version.version
                                    )
                                downAppDialog!!.onClickInstallApk = {
                                    if (!checkInstallAllowed()) {
                                        gotoSetting()
                                    } else {
                                        installApk(mContext, fileName)
                                        downAppDialog!!.dismiss()
                                    }
                                }
                            }
                            downAppDialog!!.show()
                        }
                    }.start()
            }
            dialog!!.show()
        }
    }
}
